/*
 * Copyright (C) 2022 Rockchip Electronics Co., Ltd.
 * Authors:
 *  Cerf Yu <cerf.yu@rock-chips.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _RGA_IM2D_TYPE_H_
#define _RGA_IM2D_TYPE_H_

#include <stdint.h>

#include "rga.h"

#define IM_API /* define API export as needed */

#ifdef __cplusplus
#define IM_C_API extern "C"
#define IM_EXPORT_API extern "C"
#else
#define IM_C_API
#define IM_EXPORT_API
#endif

#ifdef __cplusplus
#define DEFAULT_INITIALIZER(x) = x
#else
#define DEFAULT_INITIALIZER(x)
#endif

typedef uint32_t im_api_version_t;
typedef uint32_t im_job_handle_t;
typedef uint32_t im_ctx_id_t;
typedef uint32_t rga_buffer_handle_t;

typedef enum {
  /* Rotation */
  IM_HAL_TRANSFORM_ROT_90 = 1 << 0,
  IM_HAL_TRANSFORM_ROT_180 = 1 << 1,
  IM_HAL_TRANSFORM_ROT_270 = 1 << 2,
  IM_HAL_TRANSFORM_FLIP_H = 1 << 3,
  IM_HAL_TRANSFORM_FLIP_V = 1 << 4,
  IM_HAL_TRANSFORM_FLIP_H_V = 1 << 5,
  IM_HAL_TRANSFORM_MASK = 0x3f,

  /*
   * Blend
   * Additional blend usage, can be used with both source and target configs.
   * If none of the below is set, the default "SRC over DST" is applied.
   */
  IM_ALPHA_BLEND_SRC_OVER = 1 << 6,  /* Default, Porter-Duff "SRC over DST" */
  IM_ALPHA_BLEND_SRC = 1 << 7,       /* Porter-Duff "SRC" */
  IM_ALPHA_BLEND_DST = 1 << 8,       /* Porter-Duff "DST" */
  IM_ALPHA_BLEND_SRC_IN = 1 << 9,    /* Porter-Duff "SRC in DST" */
  IM_ALPHA_BLEND_DST_IN = 1 << 10,   /* Porter-Duff "DST in SRC" */
  IM_ALPHA_BLEND_SRC_OUT = 1 << 11,  /* Porter-Duff "SRC out DST" */
  IM_ALPHA_BLEND_DST_OUT = 1 << 12,  /* Porter-Duff "DST out SRC" */
  IM_ALPHA_BLEND_DST_OVER = 1 << 13, /* Porter-Duff "DST over SRC" */
  IM_ALPHA_BLEND_SRC_ATOP = 1 << 14, /* Porter-Duff "SRC ATOP" */
  IM_ALPHA_BLEND_DST_ATOP = 1 << 15, /* Porter-Duff "DST ATOP" */
  IM_ALPHA_BLEND_XOR = 1 << 16,      /* Xor */
  IM_ALPHA_BLEND_MASK = 0x1ffc0,

  IM_ALPHA_COLORKEY_NORMAL = 1 << 17,
  IM_ALPHA_COLORKEY_INVERTED = 1 << 18,
  IM_ALPHA_COLORKEY_MASK = 0x60000,

  IM_SYNC = 1 << 19,
  IM_CROP = 1 << 20, /* Unused */
  IM_COLOR_FILL = 1 << 21,
  IM_COLOR_PALETTE = 1 << 22,
  IM_NN_QUANTIZE = 1 << 23,
  IM_ROP = 1 << 24,
  IM_ALPHA_BLEND_PRE_MUL = 1 << 25,
  IM_ASYNC = 1 << 26,
  IM_MOSAIC = 1 << 27,
  IM_OSD = 1 << 28,
  IM_PRE_INTR = 1 << 29,
} IM_USAGE;

typedef enum {
  IM_RASTER_MODE = 1 << 0,
  IM_FBC_MODE = 1 << 1,
  IM_TILE_MODE = 1 << 2,
} IM_RD_MODE;

typedef enum {
  IM_SCHEDULER_RGA3_CORE0 = 1 << 0,
  IM_SCHEDULER_RGA3_CORE1 = 1 << 1,
  IM_SCHEDULER_RGA2_CORE0 = 1 << 2,
  IM_SCHEDULER_RGA3_DEFAULT = IM_SCHEDULER_RGA3_CORE0,
  IM_SCHEDULER_RGA2_DEFAULT = IM_SCHEDULER_RGA2_CORE0,
  IM_SCHEDULER_MASK = 0x7,
  IM_SCHEDULER_DEFAULT = 0,
} IM_SCHEDULER_CORE;

typedef enum {
  IM_ROP_AND = 0x88,
  IM_ROP_OR = 0xee,
  IM_ROP_NOT_DST = 0x55,
  IM_ROP_NOT_SRC = 0x33,
  IM_ROP_XOR = 0xf6,
  IM_ROP_NOT_XOR = 0xf9,
} IM_ROP_CODE;

typedef enum {
  IM_MOSAIC_8 = 0x0,
  IM_MOSAIC_16 = 0x1,
  IM_MOSAIC_32 = 0x2,
  IM_MOSAIC_64 = 0x3,
  IM_MOSAIC_128 = 0x4,
} IM_MOSAIC_MODE;

typedef enum {
  IM_BORDER_CONSTANT =
      0, /* iiiiii|abcdefgh|iiiiiii with some specified value 'i' */
  IM_BORDER_REFLECT = 2, /* fedcba|abcdefgh|hgfedcb */
  IM_BORDER_WRAP = 3,    /* cdefgh|abcdefgh|abcdefg */
} IM_BORDER_TYPE;

/* Status codes, returned by any blit function */
typedef enum {
  IM_YUV_TO_RGB_BT601_LIMIT = 1 << 0,
  IM_YUV_TO_RGB_BT601_FULL = 2 << 0,
  IM_YUV_TO_RGB_BT709_LIMIT = 3 << 0,
  IM_YUV_TO_RGB_MASK = 3 << 0,
  IM_RGB_TO_YUV_BT601_FULL = 1 << 2,
  IM_RGB_TO_YUV_BT601_LIMIT = 2 << 2,
  IM_RGB_TO_YUV_BT709_LIMIT = 3 << 2,
  IM_RGB_TO_YUV_MASK = 3 << 2,
  IM_RGB_TO_Y4 = 1 << 4,
  IM_RGB_TO_Y4_DITHER = 2 << 4,
  IM_RGB_TO_Y1_DITHER = 3 << 4,
  IM_Y4_MASK = 3 << 4,
  IM_RGB_FULL = 1 << 8,
  IM_RGB_CLIP = 2 << 8,
  IM_YUV_BT601_LIMIT_RANGE = 3 << 8,
  IM_YUV_BT601_FULL_RANGE = 4 << 8,
  IM_YUV_BT709_LIMIT_RANGE = 5 << 8,
  IM_YUV_BT709_FULL_RANGE = 6 << 8,
  IM_FULL_CSC_MASK = 0xf << 8,
  IM_COLOR_SPACE_DEFAULT = 0,
} IM_COLOR_SPACE_MODE;

typedef enum {
  IM_UP_SCALE,
  IM_DOWN_SCALE,
} IM_SCALE;

typedef enum {
  INTER_NEAREST,
  INTER_LINEAR,
  INTER_CUBIC,
} IM_SCALE_MODE;

typedef enum {
  IM_CONFIG_SCHEDULER_CORE,
  IM_CONFIG_PRIORITY,
  IM_CONFIG_CHECK,
} IM_CONFIG_NAME;

typedef enum {
  IM_OSD_MODE_STATISTICS = 0x1 << 0,
  IM_OSD_MODE_AUTO_INVERT = 0x1 << 1,
} IM_OSD_MODE;

typedef enum {
  IM_OSD_INVERT_CHANNEL_NONE = 0x0,
  IM_OSD_INVERT_CHANNEL_Y_G = 0x1 << 0,
  IM_OSD_INVERT_CHANNEL_C_RB = 0x1 << 1,
  IM_OSD_INVERT_CHANNEL_ALPHA = 0x1 << 2,
  IM_OSD_INVERT_CHANNEL_COLOR =
      IM_OSD_INVERT_CHANNEL_Y_G | IM_OSD_INVERT_CHANNEL_C_RB,
  IM_OSD_INVERT_CHANNEL_BOTH =
      IM_OSD_INVERT_CHANNEL_COLOR | IM_OSD_INVERT_CHANNEL_ALPHA,
} IM_OSD_INVERT_CHANNEL;

typedef enum {
  IM_OSD_FLAGS_INTERNAL = 0,
  IM_OSD_FLAGS_EXTERNAL,
} IM_OSD_FLAGS_MODE;

typedef enum {
  IM_OSD_INVERT_USE_FACTOR,
  IM_OSD_INVERT_USE_SWAP,
} IM_OSD_INVERT_MODE;

typedef enum {
  IM_OSD_BACKGROUND_DEFAULT_BRIGHT = 0,
  IM_OSD_BACKGROUND_DEFAULT_DARK,
} IM_OSD_BACKGROUND_DEFAULT;

typedef enum {
  IM_OSD_BLOCK_MODE_NORMAL = 0,
  IM_OSD_BLOCK_MODE_DIFFERENT,
} IM_OSD_BLOCK_WIDTH_MODE;

typedef enum {
  IM_OSD_MODE_HORIZONTAL,
  IM_OSD_MODE_VERTICAL,
} IM_OSD_DIRECTION;

typedef enum {
  IM_OSD_COLOR_PIXEL,
  IM_OSD_COLOR_EXTERNAL,
} IM_OSD_COLOR_MODE;

typedef enum {
  IM_INTR_READ_INTR = 1 << 0,
  IM_INTR_READ_HOLD = 1 << 1,
  IM_INTR_WRITE_INTR = 1 << 2,
} IM_PRE_INTR_FLAGS;

typedef enum {
  IM_CONTEXT_NONE = 0x0,
  IM_CONTEXT_SRC_FIX_ENABLE =
      0x1 << 0, // Enable kernel to modify the image parameters of the channel.
  IM_CONTEXT_SRC_CACHE_INFO = 0x1 << 1, // It will replace the parameters in ctx
                                        // with the modified parameters.
  IM_CONTEXT_SRC1_FIX_ENABLE = 0x1 << 2,
  IM_CONTEXT_SRC1_CACHE_INFO = 0x1 << 3,
  IM_CONTEXT_DST_FIX_ENABLE = 0x1 << 4,
  IM_CONTEXT_DST_CACHE_INFO = 0x1 << 5,
} IM_CONTEXT_FLAGS;

/* Get RGA basic information index */
typedef enum {
  RGA_VENDOR = 0,
  RGA_VERSION,
  RGA_MAX_INPUT,
  RGA_MAX_OUTPUT,
  RGA_BYTE_STRIDE,
  RGA_SCALE_LIMIT,
  RGA_INPUT_FORMAT,
  RGA_OUTPUT_FORMAT,
  RGA_FEATURE,
  RGA_EXPECTED,
  RGA_ALL,
} IM_INFORMATION;

/* Status codes, returned by any blit function */
typedef enum {
  IM_STATUS_NOERROR = 2,
  IM_STATUS_SUCCESS = 1,
  IM_STATUS_NOT_SUPPORTED = -1,
  IM_STATUS_OUT_OF_MEMORY = -2,
  IM_STATUS_INVALID_PARAM = -3,
  IM_STATUS_ILLEGAL_PARAM = -4,
  IM_STATUS_ERROR_VERSION = -5,
  IM_STATUS_FAILED = 0,
} IM_STATUS;

/* Rectangle definition */
typedef struct {
  int x;      /* upper-left x */
  int y;      /* upper-left y */
  int width;  /* width */
  int height; /* height */
} im_rect;

typedef struct {
  int max; /* The Maximum value of the color key */
  int min; /* The minimum value of the color key */
} im_colorkey_range;

typedef struct im_nn {
  int scale_r;  /* scaling factor on R channal */
  int scale_g;  /* scaling factor on G channal */
  int scale_b;  /* scaling factor on B channal */
  int offset_r; /* offset on R channal */
  int offset_g; /* offset on G channal */
  int offset_b; /* offset on B channal */
} im_nn_t;

/* im_info definition */
typedef struct {
  void *vir_addr; /* virtual address */
  void *phy_addr; /* physical address */
  int fd;         /* shared fd */

  int width;   /* width */
  int height;  /* height */
  int wstride; /* wstride */
  int hstride; /* hstride */
  int format;  /* format */

  int color_space_mode; /* color_space_mode */
  int global_alpha;     /* global_alpha */
  int rd_mode;

  /* legarcy */
  int color;                        /* color, used by color fill */
  im_colorkey_range colorkey_range; /* range value of color key */
  im_nn_t nn;
  int rop_code;

  rga_buffer_handle_t handle; /* buffer handle */
} rga_buffer_t;

typedef struct im_color {
  union {
    struct {
      uint8_t red;
      uint8_t green;
      uint8_t blue;
      uint8_t alpha;
    };
    uint32_t value;
  };
} im_color_t;

typedef struct im_osd_invert_factor {
  uint8_t alpha_max;
  uint8_t alpha_min;
  uint8_t yg_max;
  uint8_t yg_min;
  uint8_t crb_max;
  uint8_t crb_min;
} im_osd_invert_factor_t;

typedef struct im_osd_bpp2 {
  uint8_t ac_swap;     // ac swap flag
                       // 0: CA
                       // 1: AC
  uint8_t endian_swap; // rgba2bpp endian swap
                       // 0: Big endian
                       // 1: Little endian
  im_color_t color0;
  im_color_t color1;
} im_osd_bpp2_t;

typedef struct im_osd_block {
  int width_mode; // normal or different
                  //   IM_OSD_BLOCK_MODE_NORMAL
                  //   IM_OSD_BLOCK_MODE_DIFFERENT
  union {
    int width;       // normal_mode block width
    int width_index; // different_mode block width index in RAM
  };

  int block_count; // block count

  int background_config; // background config is bright or dark
                         //   IM_OSD_BACKGROUND_DEFAULT_BRIGHT
                         //   IM_OSD_BACKGROUND_DEFAULT_DARK

  int direction; // osd block direction
                 //   IM_OSD_MODE_HORIZONTAL
                 //   IM_OSD_MODE_VERTICAL

  int color_mode;          // using src1 color or config color
                           //   IM_OSD_COLOR_PIXEL
                           //   IM_OSD_COLOR_EXTERNAL
  im_color_t normal_color; // config color: normal
  im_color_t invert_color; // config color: invert
} im_osd_block_t;

typedef struct im_osd_invert {
  int invert_channel; // invert channel config:
                      //   IM_OSD_INVERT_CHANNEL_NONE
                      //   IM_OSD_INVERT_CHANNEL_Y_G
                      //   IM_OSD_INVERT_CHANNEL_C_RB
                      //   IM_OSD_INVERT_CHANNEL_ALPHA
                      //   IM_OSD_INVERT_CHANNEL_COLOR
                      //   IM_OSD_INVERT_CHANNEL_BOTH
  int flags_mode;     // use external or inertnal RAM invert flags
                      //   IM_OSD_FLAGS_EXTERNAL
                      //   IM_OSD_FLAGS_INTERNAL
  int flags_index;    // flags index when using internal RAM invert flags

  uint64_t invert_flags;  // external invert flags
  uint64_t current_flags; // current flags

  int invert_mode; // invert use swap or factor
                   //   IM_OSD_INVERT_USE_FACTOR
                   //   IM_OSD_INVERT_USE_SWAP
  im_osd_invert_factor_t factor;

  int threash;
} im_osd_invert_t;

typedef struct im_osd {
  int osd_mode;              // osd mode: statistics or auto_invert
                             //   IM_OSD_MODE_STATISTICS
                             //   IM_OSD_MODE_AUTO_INVERT
  im_osd_block_t block_parm; // osd block info config

  im_osd_invert_t invert_config;

  im_osd_bpp2_t bpp2_info;
} im_osd_t;

typedef struct im_intr_config {
  uint32_t flags;

  int read_threshold;
  int write_start;
  int write_step;
} im_intr_config_t;

typedef struct im_opt {
  im_api_version_t version DEFAULT_INITIALIZER(RGA_CURRENT_API_HEADER_VERSION);

  int color;                        /* color, used by color fill */
  im_colorkey_range colorkey_range; /* range value of color key */
  im_nn_t nn;
  int rop_code;

  int priority;
  int core;

  int mosaic_mode;

  im_osd_t osd_config;

  im_intr_config_t intr_config;

  char reserve[128];
} im_opt_t;

typedef struct im_handle_param {
  uint32_t width;
  uint32_t height;
  uint32_t format;
} im_handle_param_t;

#endif /* _RGA_IM2D_TYPE_H_ */
